package com.ddm.interceptor;

import com.ddm.constant.JwtClaimsConstant;
import com.ddm.context.BaseContext;
import com.ddm.properties.JwtProperties;
import com.ddm.properties.OpenProperties;
import com.ddm.utils.JwtUtil;
import com.ddm.utils.WebJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 校验用户登录状态的拦截器，支持微信用户、管理员和普通web用户
 * 管理员id固定为1，及第一个用户
 */
@Component
@Slf4j
public class OpenIdTokenInterceptor implements HandlerInterceptor {

    @Autowired
    private WebJwtUtil jwtUtil;
    @Autowired
    private OpenProperties openProperties;
    @Autowired
    private JwtProperties jwtProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 非Controller方法直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // 提取token
        String token = request.getHeader("token");
        String adminToken = request.getHeader(jwtProperties.getAdminTokenName());
        log.debug("请求头中的token: {}", token);
        log.debug("请求头中的adminToken: {}", adminToken);

        // 1. 尝试微信用户验证
        if (validateWechatUser(token)) {
            return true;
        }

        // 2. 尝试管理员验证
        if (validateAdminUser(adminToken)) {
            return true;
        }

        // 3. 尝试普通web用户验证
        if (validateWebUser(token)) {
            return true;
        }

        // 验证失败，返回401
        log.warn("请求验证失败，返回401状态码");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }

    /**
     * 验证微信用户
     */
    private boolean validateWechatUser(String token) {
        if (token == null) {
            return false;
        }

        try {
            Claims claims = JwtUtil.parseJWT(openProperties.getAppSecret(), token);
            Long userId = getUserIdFromClaims(claims);
            log.info("微信用户验证成功，用户ID: {}", userId);
            BaseContext.setCurrentId(userId);
            return true;
        } catch (Exception e) {
            log.debug("微信用户验证失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 验证管理员用户
     */
    private boolean validateAdminUser(String adminToken) {
        if (adminToken == null) {
            return false;
        }

        try {
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), adminToken);
            Long adminId = Long.valueOf(claims.get(JwtClaimsConstant.ADMIN_ID).toString());
//            Long adminId=1L;//特别注意
            log.info("管理员验证成功，管理员ID: {}", adminId);
            BaseContext.setCurrentId(adminId);
            return true;
        } catch (Exception e) {
            log.debug("管理员验证失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 验证普通web用户
     */
    private boolean validateWebUser(String token) {
        if (token == null) {
            return false;
        }

        try {
            Claims claims = jwtUtil.parseJwt(token);
            log.debug("Web用户JWT解析成功，Claims: {}", claims);

            Long userId = getUserIdFromClaims(claims);
            if (userId != null) {
                log.info("Web用户验证成功，用户ID: {}", userId);
                BaseContext.setCurrentId(userId);
            }
            return true;
        } catch (Exception e) {
            log.debug("Web用户验证失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 从Claims中安全获取用户ID
     */
    private Long getUserIdFromClaims(Claims claims) {
        Object userIdObj = claims.get(JwtClaimsConstant.USER_ID);
        if (userIdObj != null) {
            try {
                return Long.valueOf(userIdObj.toString());
            } catch (NumberFormatException e) {
                log.error("用户ID格式错误: {}", userIdObj);
            }
        }
        return null;
    }
}